#include <jni.h>
#include <string>
#include <android/log.h>

jobject createJavaBean(JNIEnv *env, int index);

extern "C" JNIEXPORT jstring

#define LOG_TAG "CPPLOG"
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG , __VA_ARGS__) // 定义LOGD类型
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG , __VA_ARGS__) // 定义LOGE类型
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG , __VA_ARGS__) // 定义LOGE类型


JNICALL
Java_com_heiko_myndktest_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

jobject createJavaBean(JNIEnv *env, int index) {
    jclass clazz = env->FindClass("com/heiko/myndktest/JavaBean");
    /*if (cls_hello== nullptr){
        throw ""
    }*/

    jmethodID constructorId = env->GetMethodID(clazz, "<init>", "()V");
    // 调用构造方法创建新对象
    jobject newObj = env->NewObject(clazz, constructorId);

    //赋值public int
    jfieldID myIntFiledId = env->GetFieldID(clazz, "myPublicInt", "I");

    jint myPublicInt = env->GetIntField(newObj, myIntFiledId);
    LOGD("myPublicInt %d", myPublicInt);

    env->SetIntField(newObj, myIntFiledId, index);

    //赋值public float
    jfieldID myFloatFiledId = env->GetFieldID(clazz, "myPublicFloat", "F");

    jfloat myPublicFloat = env->GetFloatField(newObj, myFloatFiledId);
    LOGD("myPublicFloat %f", myPublicFloat);

    jfloat floatValue1 = 5.67f;
    env->SetFloatField(newObj, myFloatFiledId, floatValue1);


    //赋值public string
    jfieldID myStringFiledId = env->GetFieldID(clazz, "myPublicString", "Ljava/lang/String;");

    //jstring stringResult = (jstring)env->GetObjectField(newObj, myStringFiledId);
    jstring mPublicString = static_cast<jstring>(env->GetObjectField(newObj, myStringFiledId));
    const char *mPublicStringUTFChars = env->GetStringUTFChars(mPublicString, nullptr);
    LOGD("stringResult %s", mPublicStringUTFChars);
    //别忘了释放资源
    env->ReleaseStringUTFChars(mPublicString, mPublicStringUTFChars);

    const char *stringValue = "你好呀";
    jstring javaStringValue = env->NewStringUTF(stringValue);
    env->SetObjectField(newObj, myStringFiledId, javaStringValue);

    //获取float方法
    jmethodID getFloatValueMethodId = env->GetMethodID(clazz, "getFloatValue", "()F");
    jfloat javaFloatValue = env->CallFloatMethod(newObj, getFloatValueMethodId);
    LOGD("javaFloatValue:%f", javaFloatValue);

    //设置float方法
    jmethodID setFloatValueMethodId = env->GetMethodID(clazz, "setFloatValue", "(F)V");
    jfloat floatValue = 3.14f;
    env->CallVoidMethod(newObj, setFloatValueMethodId, floatValue);

    //获得string方法返回值
    jmethodID getStringValueMethodId = env->GetMethodID(clazz, "getStringValue",
                                                        "()Ljava/lang/String;");
    jstring stringMethodValue = (jstring) env->CallObjectMethod(newObj, getStringValueMethodId);
    const char *stringMethodValueChars = env->GetStringUTFChars(stringMethodValue, nullptr);
    LOGD("stringMethodValue %s", stringMethodValueChars);
    //别忘了释放资源
    env->ReleaseStringUTFChars(mPublicString, stringMethodValueChars);

    //设置sring方法
    jmethodID setStringValueMethodId = env->GetMethodID(clazz, "setStringValue",
                                                        "(Ljava/lang/String;)V");
    const char *sss = "我的天!";
    jstring ssss = env->NewStringUTF(sss);
    env->CallVoidMethod(newObj, setStringValueMethodId, ssss);

    //获取float[]
    jfieldID myPublicFloatArrayFiledId = env->GetFieldID(clazz, "myPublicFloatArray", "[F");
    jfloatArray myPublicFloatArray = (jfloatArray) env->GetObjectField(newObj,
                                                                       myPublicFloatArrayFiledId);
    // 获取数组长度
    jsize myPublicFloatArrayLen = env->GetArrayLength(myPublicFloatArray);
    // 获取jfloatArray的本地引用和元素指针
    jboolean *isCopy = nullptr;
    jfloat *elements = env->GetFloatArrayElements(myPublicFloatArray, isCopy);

    for (int i = 0; i < myPublicFloatArrayLen; ++i) {
        if (i == 1) {
            //修改某个索引值
            elements[i] = 9.91f;
        }
        LOGD("myPublicFloatArray[%d]:%f", i, elements[i]);
    }

    //设置float[]
    jfloatArray newFloatArray = env->NewFloatArray(5);
    jfloat *elements2 = env->GetFloatArrayElements(newFloatArray, nullptr);
    for (int i = 0; i < 5; ++i) {
        elements2[i] = 2.2f * i;
    }
    env->SetObjectField(newObj, myPublicFloatArrayFiledId, newFloatArray);
    //释放
    env->ReleaseFloatArrayElements(newFloatArray, elements2, 0);

    // 释放本地引用和元素指针
    env->ReleaseFloatArrayElements(myPublicFloatArray, elements, 0);

    return newObj;
}

extern "C"
JNIEXPORT jobject JNICALL
Java_com_heiko_myndktest_MainActivity_test3(JNIEnv *env, jobject thiz) {
    jobject newObj = createJavaBean(env, 9);
    return newObj;
}
extern "C"
JNIEXPORT jobjectArray JNICALL
Java_com_heiko_myndktest_MainActivity_test4(JNIEnv *env, jobject thiz) {
    jclass clazz = env->FindClass("com/heiko/myndktest/JavaBean");
    jobjectArray objArray = env->NewObjectArray(5, clazz, NULL);
    for (int i = 0; i < 5; ++i) {
        jobject newObj = createJavaBean(env, i);
        env->SetObjectArrayElement(objArray, i, newObj);
    }

    return objArray;
}
extern "C"
JNIEXPORT jobject JNICALL
Java_com_heiko_myndktest_MainActivity_test1(JNIEnv *env, jobject thiz) {
    jclass mapClass = env->FindClass("java/util/HashMap");
    jmethodID initMethod = env->GetMethodID(mapClass, "<init>", "()V");
    jobject javaMap = env->NewObject(mapClass, initMethod);

    jmethodID putMethod = env->GetMethodID(mapClass, "put",
                                           "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
    jstring keyString = env->NewStringUTF("key1"); // 示例：创建一个字符串键
    jstring valueString = env->NewStringUTF("value1"); // 假设value是一个字符串

    env->CallObjectMethod(javaMap, putMethod, keyString, valueString);

    return javaMap;
}
extern "C"
JNIEXPORT jobject JNICALL
Java_com_heiko_myndktest_MainActivity_test2(JNIEnv *env, jobject thiz) {
    jclass mapClass = env->FindClass("java/util/HashMap");
    jmethodID initMethod = env->GetMethodID(mapClass, "<init>", "()V");
    jobject javaMap = env->NewObject(mapClass, initMethod);

    jmethodID putMethod = env->GetMethodID(mapClass, "put",
                                           "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
    jstring keyString = env->NewStringUTF("myKey"); // 示例：创建一个字符串键

    // 创建Java Integer数组类对象
    jclass integerClass = env->FindClass("java/lang/Integer");
    jobjectArray javaArray = env->NewObjectArray(5, integerClass, nullptr);
    // 假设你有一个C++端的int数组或者其他结构存储数据
    jint nativeData[5] = {1, 2, 3, 4, 5}; // 这里填充实际的数据

    for (jint i = 0; i < 5; ++i) {
        // 将C++中的int值转换为Java的Integer对象
        jmethodID integerValueOfMethod = env->GetStaticMethodID(integerClass, "valueOf", "(I)Ljava/lang/Integer;");
        jobject javaInteger = env->CallStaticObjectMethod(integerClass, integerValueOfMethod, nativeData[i]);

        // 将Java Integer对象添加到数组中
        env->SetObjectArrayElement(javaArray, i, javaInteger);

        // 删除局部引用以避免内存泄漏（可选，在JNI调用结束时自动发生）
        env->DeleteLocalRef(javaInteger);
    }

    env->CallObjectMethod(javaMap, putMethod, keyString, javaArray);

    return javaMap;
}
extern "C"
JNIEXPORT jobjectArray JNICALL
Java_com_heiko_myndktest_MainActivity_test5(JNIEnv *env, jobject thiz) {
    int rows = 5; // 行数
    int cols = 4; // 列数

    jclass intClass = env->FindClass("[I");
    jobjectArray result = env->NewObjectArray(rows, intClass, NULL);
    for (jint i = 0; i < rows; i++) {
        jintArray intArray = env->NewIntArray(cols);
        jint *elements = env->GetIntArrayElements(intArray, nullptr);
        if (elements == nullptr) {
            env->DeleteLocalRef(intArray);
            return nullptr;
        }
        elements[0] = i * 4 + 0;
        elements[1] = i * 4 + 1;
        elements[2] = i * 4 + 2;
        elements[3] = i * 4 + 3;
        env->ReleaseIntArrayElements(intArray, elements, 0);
        env->SetObjectArrayElement(result, i, intArray);
    }
    return result;
}